Skip to content

feat(llm): allow configuring a default model per provider#10009

Open
Halone228 wants to merge 3 commits into
TriliumNext:mainfrom
Halone228:main
Open

feat(llm): allow configuring a default model per provider#10009
Halone228 wants to merge 3 commits into
TriliumNext:mainfrom
Halone228:main

Conversation

@Halone228

Copy link
Copy Markdown

Adds an optional 'Model' field to the AI provider configuration dialog. When set, the model is injected into the available models list as the default and used as a fallback in chat requests.

  • Add model?: string to LlmProviderConfig (client) and LlmProviderSetup (server)
  • Add model input to AddProviderModal
  • Show configured model in ProviderList table
  • Merge configured model into getAllModels() and llm_chat stream
  • Add translations (en, ru)
  • Update and extend tests

Related to #10008

Adds an optional 'Model' field to the AI provider configuration dialog.
When set, the model is injected into the available models list as the
default and used as a fallback in chat requests.

- Add model?: string to LlmProviderConfig (client) and LlmProviderSetup (server)
- Add model input to AddProviderModal
- Show configured model in ProviderList table
- Merge configured model into getAllModels() and llm_chat stream
- Add translations (en, ru)
- Update and extend tests
@dosubot dosubot Bot added the size:M This PR changes 30-99 lines, ignoring generated files. label May 31, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the ability to configure an optional model ID for LLM providers, updating both the client UI (provider list and add provider modal) and the server-side LLM service to support this configuration. Feedback on the changes highlights an issue in the server-side model resolution logic where configuring a custom model can result in multiple models being marked as default (isDefault: true) for the same provider, and a code suggestion is provided to ensure only the configured model is marked as default.

Comment thread apps/server/src/services/llm/index.ts
When a custom model is configured, unset isDefault on all other models
so the client UI never sees multiple defaults for the same provider.
@greptile-apps

greptile-apps Bot commented May 31, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds an optional Model field to the AI provider configuration, letting users pin a specific model ID per provider. When set, the model is injected as the default in getAllModels() and used as a fallback in streamChat when the client does not specify one.

  • Server (index.ts): LlmProviderSetup gains model?: string; getAllModels marks the configured model as isDefault (or prepends it when absent from the provider's static list); a new getProviderSetupByType export exposes the setup config for a provider type.
  • Server (llm_chat.ts): streamChat resolves effectiveModel = config.model || setup?.model so a provider-level default is applied when the client omits a model.
  • Client: AddProviderModal gains a trimmed, optional model input; ProviderList shows the configured model (or a "Default" placeholder) in the table; translations are added for EN and RU.

Confidence Score: 5/5

Safe to merge; the feature is additive and purely opt-in — omitting the new field leaves all existing behavior unchanged.

All changed paths are guarded by optional fields with clear fallbacks. The model-injection logic in getAllModels correctly handles both the 'model already in list' and 'model not in list' cases and strips isDefault from other entries. The streamChat fallback chain (config.model → setup.model → provider default → error) is well-structured. The one gap (handler-level test for the setup.model fallback) is a coverage nit that does not affect correctness.

No files require special attention; the test gap in llm_chat.spec.ts is the only item worth a follow-up.

Important Files Changed

Filename Overview
apps/server/src/services/llm/index.ts Adds model to LlmProviderSetup, new getProviderSetupByType export, and model-injection logic in getAllModels that marks a configured model as isDefault or prepends it when absent from the provider list.
apps/server/src/routes/api/llm_chat.ts Adds getProviderSetupByType call to resolve setup?.model as a fallback after the client-specified model. Logic is sound; config.model (client) takes precedence over setup.model (server config).
apps/server/src/services/llm/index.spec.ts Adds tests for custom-model injection (both existing and new model IDs) and getProviderSetupByType resolution; coverage is thorough at the service layer.
apps/server/src/routes/api/llm_chat.spec.ts Adds getProviderSetupByType to the mock but hardcodes it to return undefined, leaving the setup?.model fallback path in streamChat untested.
apps/client/src/widgets/type_widgets/options/llm/AddProviderModal.tsx Adds optional model field to the add-provider form with proper state, trim, reset, and conditional spread into the saved config.

Sequence Diagram

sequenceDiagram
    participant Client
    participant streamChat
    participant getProviderByType
    participant getProviderSetupByType
    participant Provider

    Client->>streamChat: "POST /llm/chat {config: {provider, model?}}"
    streamChat->>getProviderByType: getProviderByType(config.provider)
    getProviderByType-->>streamChat: LlmProvider instance
    streamChat->>getProviderSetupByType: getProviderSetupByType(config.provider)
    getProviderSetupByType-->>streamChat: "LlmProviderSetup {model?}"
    Note over streamChat: effectiveModel = config.model || setup?.model
    streamChat->>Provider: "chat(messages, {...config, model: effectiveModel})"
    Provider-->>streamChat: StreamResult
    streamChat-->>Client: SSE chunks
Loading

Fix All in Claude Code

Reviews (2): Last reviewed commit: "Update apps/client/src/translations/ru/t..." | Re-trigger Greptile

Comment thread apps/client/src/translations/ru/translation.json Outdated
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-conflicts size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants